/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pe.gps.servlet;

import com.google.gson.Gson;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
import pe.gps.server.GPSFactory;
import pe.gps.service.Servicio;
import pe.gps.service.ServicioSO;
import pe.gps.service.ServicioTCP;
import pe.gps.service.ServicioWR;
import pe.gps.util.GpsStatus;

/**
 *
 * @author Romulo Galindo Tanta
 */
public class GPSWebSocketStatusServlet extends WebSocketServlet implements Runnable {

    private static final Map<String, WebSocketConnection> connections = new HashMap<>();
    Thread thread;
    boolean run;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        run = true;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void destroy() {
        super.destroy();
        try {
            run = false;
        } catch (Exception ep) {
        }
    }

    @Override
    protected boolean verifyOrigin(String origin) {
        return true;
    }

    @Override
    protected StreamInbound createWebSocketInbound(String string, HttpServletRequest hsr) {
        final String connectionId = hsr.getSession().getId();
        WebSocketConnection sc = new WebSocketConnection(connectionId);
        return sc;
    }

    @Override
    public void run() {
        while (run) {
            for (WebSocketConnection connection : connections.values()) {
                try {
                    CharBuffer buffer = CharBuffer.wrap(buildmessage());
                    connection.getWsOutbound().writeTextMessage(buffer);
                } catch (IOException ignore) {

                }
            }
            try {
                Thread.sleep(2000);
            } catch (Exception ep) {
            }
        }
    }

    public String buildmessage() {
        Date date = new Date();
        GpsStatus gps = new GpsStatus();
        gps.setFecha_a(new SimpleDateFormat("hh:mm:ss").format(date));
        gps.setFecha_b(new SimpleDateFormat("dd/MM/yyyy").format(date));
        List<pe.gps.util.ServicioTCP> tcps = new ArrayList<>();
        List<pe.gps.util.ServicioWR> wrs = new ArrayList<>();
        List<pe.gps.util.ServicioSO> sos = new ArrayList<>();

        for (Servicio s : GPSFactory.getServer().getServicios()) {
            switch (s.getCo_type()) {
                case "TCP": {
                    ServicioTCP tcp = (ServicioTCP) s;
                    pe.gps.util.ServicioTCP sc = new pe.gps.util.ServicioTCP();
                    sc.setId(tcp.getNo_server());
                    if (tcp.getCa_disgps() > 0) {
                        sc.setImg("img/green.png");
                    } else {
                        sc.setImg("img/orange.jpeg");
                    }
                    sc.setMegabytes("" + tcp.getMegabytes());
                    sc.setCa_disgps(tcp.getCa_disgps());
                    sc.setTm_min(tcp.getTm_minimo());
                    sc.setTm_max(tcp.getTm_maximo());
                    sc.setRecords(tcp.getRecords());
                    tcps.add(sc);
                    break;
                }
                case "WR": {
                    ServicioWR wr = (ServicioWR) s;
                    pe.gps.util.ServicioWR sc = new pe.gps.util.ServicioWR();
                    sc.setId(wr.getNo_server());
                    if (wr.getCa_process() > 0) {
                        sc.setImg("img/green.png");
                    } else {
                        sc.setImg("img/orange.jpeg");
                    }
                    sc.setSizeThread("" + wr.getSizethread());
                    sc.setRegistros("" + wr.getCa_process());
                    sc.setAtendidos("" + wr.getCa_process_ok());
                    sc.setPendientes("" + wr.getCa_process_wait());
                    sc.setPs("" + wr.getCa_ps());
                    wrs.add(sc);
                    break;
                }
                case "SO": {
                    ServicioSO so = (ServicioSO) s;
                    pe.gps.util.ServicioSO sc = new pe.gps.util.ServicioSO();
                    sc.setId("" + so.getNo_server());
                    sc.setExe("" + so.getCa_exec());
                    sos.add(sc);
                    break;
                }
            }
        }
        gps.setTCP(tcps);
        gps.setWR(wrs);
        gps.setSO(sos);
        String json = new Gson().toJson(gps);
        return json;
    }

    private static class WebSocketConnection extends MessageInbound {

        private final String connectionId;
        private final Gson jsonProcessor;

        private WebSocketConnection(String connectionId) {
            this.connectionId = connectionId;
            this.jsonProcessor = new Gson();
        }

        @Override
        protected void onOpen(WsOutbound outbound) {
            System.out.println("Conexion abierta!");
            connections.put(connectionId, this);
        }

        @Override
        protected void onClose(int status) {
            System.out.println("Conexion cerrada!");
            connections.remove(connectionId);
        }

        @Override
        protected void onBinaryMessage(ByteBuffer bb) throws IOException {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        protected void onTextMessage(CharBuffer cb) throws IOException {
            final String user = cb.toString();
            System.out.println("user:" + user);
            getWsOutbound().writeTextMessage(CharBuffer.wrap("Hola " + user + " desde WebSocket"));
        }
    }

}
